package com.xx.jenkinsdemo.aspect;

import com.xx.jenkinsdemo.exception.BusinessLogicException;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.AmqpRejectAndDontRequeueException;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.stereotype.Component;

/**
 * @title: ReceiveMessageAspect
 * @Author xu-xiang
 * @Date: 2025/7/10 17:25
 * @description: 对MQ任务处理进行增强
 * * 1. 对没有设置id的消息, 附加消息id
 * * 2. 对消息处理过程增加日志, 对于 BusinessLogicException业务逻辑异常, 直接丢弃消息,不再入队
 */

@Component
@Aspect
public class ReceiveMessageAspect {

    private final Logger logger = LoggerFactory.getLogger(ReceiveMessageAspect.class);

    @Pointcut(value = "@annotation(org.springframework.amqp.rabbit.annotation.RabbitListener)")
    public void pointCut() {
    }

    @Around("pointCut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        Object[] args = joinPoint.getArgs();

        if (args == null || args.length == 0) {
            return joinPoint.proceed();
        }

        Message message = null;
        for (Object arg : args) {
            if (arg instanceof Message) {
                message = (Message) arg;
                break;
            }
        }

        if (message == null) {
            return joinPoint.proceed();
        }

        MessageProperties messageProperties = message.getMessageProperties();

        String receivedExchange = messageProperties.getReceivedExchange();
        String receivedRoutingKey = messageProperties.getReceivedRoutingKey();
        String messageId = messageProperties.getMessageId();
        logger.info(
                "收到rabbitMQ消息: exchange: {}, routingKey: {}, msgId: {}",
                receivedExchange,
                receivedRoutingKey,
                messageId
        );

        try {
            Object result = joinPoint.proceed();

            logger.info(
                    "rabbitMQ消息已消费: exchange: {}, routingKey: {}, msgId: {}",
                    receivedExchange,
                    receivedRoutingKey,
                    messageId
            );

            return result;
        } catch (BusinessLogicException e) {
            throw new AmqpRejectAndDontRequeueException(e); // 业务异常不重试直接丢弃消息
        } catch (Throwable ex) {
            logger.error(
                    "rabbitMQ消息消费异常: exchange: {}, routingKey: {}, msgId: {}, exMsg: {}",
                    receivedExchange,
                    receivedRoutingKey,
                    messageId,
                    ex.getMessage()
            );
            logger.error(ExceptionUtils.getStackTrace(ex));
            throw ex;
        }
    }
}
